<template>
  <div class="tables" :class="className">
    <!-- <Card :style="{ '--minHeight': minHeight }"> -->
    <div
      class="tableContent"
      :class="{ border: contentBorder }"
      :style="{ '--minHeight': minHeight, '--padding': padding }"
    >
      <!-- 筛选权限判断代码(暂时隐藏) -->
      <!-- v-if="
          searchLimit && searchLimit.length
            ? isSearch && $hasOneOf(searchLimit, $store.state.user.access)
            : isSearch
        " -->
      <div class="flex justify-between mb-10 a-center" v-if="isSearch">
        <div class="searchInput flex flex-wrap" style="gap: 5px 0">
          <Form style="position: relative" label-position="top">
            <div
              v-for="(item, index) in searchKey"
              :key="index"
              :style="{
                width: item.divWidth
                  ? isNaN(item.divWidth)
                    ? item.divWidth
                    : item.divWidth + 'px'
                  : '18.8%',
              }"
            >
              <FormItem :label="formatterLabel(item, index)">
                <!-- 选择框 -->
                <Select
                  v-if="item.type == 'select'"
                  clearable
                  filterable
                  :multiple="item.multiple"
                  :max-tag-placeholder="maxTagPlaceholder"
                  class="mr-6"
                  :max-tag-count="item.maxTagCount || 2"
                  :style="{ width: item.width ? item.width + 'px' : '100%' }"
                  placeholder=""
                  v-model="info[item.key]"
                >
                  <!-- :placeholder="!item.isHiddenPlace ? item.placeholder : ''" -->
                  <Option
                    v-for="(option, index) in item.option"
                    :key="index"
                    :value="
                      option[
                        item.props && item.props.value
                          ? item.props.value
                          : 'value'
                      ]
                    "
                    :label="
                      option[
                        item.props && item.props.label
                          ? item.props.label
                          : 'label'
                      ]
                    "
                  ></Option> </Select
                ><!-- 日期范围搜索 -->
                <!-- :placeholder="!item.isHiddenPlace ? item.placeholder : ''" -->
                <DatePicker
                  :style="{ width: item.width ? item.width + 'px' : '100%' }"
                  v-if="item.type == 'daterange'"
                  type="daterange"
                  placement="bottom-end"
                  placeholder=""
                  class="mr-6"
                  @on-change="
                    (val, type) => changeDate(val, type, item.changeDate, item)
                  "
                  v-model="info[item.vModel]"
                  :transfer="true"
                ></DatePicker>
                <!-- 级联 -->
                <Cascader
                  v-if="item.type == 'cascader'"
                  :data="item.option"
                  v-model="info[item.vModel]"
                  @on-change="
                    (value, selectedData) =>
                      changeCas(value, selectedData, item)
                  "
                  :placeholder="item.placeholder"
                  transfer
                ></Cascader>
                <!-- 时间搜索 -->
                <TimePicker
                  :style="{ width: item.width ? item.width + 'px' : '100%' }"
                  v-if="item.type == 'timepicker'"
                  :format="item.format"
                  v-model="info[item.vModel]"
                  :transfer="true"
                  :type="item.valueType"
                  @on-change="
                    (val) => changeTimePicker(val, item.changeDate, item)
                  "
                ></TimePicker>
                <!-- 日期范围搜索(带时分秒) -->
                <!-- :placeholder="!item.isHiddenPlace ? item.placeholder : ''" -->
                <DatePicker
                  :style="{ width: item.width ? item.width + 'px' : '100%' }"
                  v-if="item.type == 'datetimerange'"
                  type="datetimerange"
                  placement="bottom-end"
                  placeholder=""
                  class="mr-6"
                  @on-change="
                    (val, type) =>
                      changeTimeDate(val, type, item.changeDate, item)
                  "
                  v-model="info[item.vModel]"
                  :format="item.format"
                  :transfer="true"
                ></DatePicker>
                <!-- 普通搜索 -->
                <!-- :placeholder="!item.isHiddenPlace ? item.placeholder : ''" -->
                <Input
                  v-if="item.type == 'input'"
                  type="text"
                  class="mr-6"
                  :style="{ width: item.width ? item.width + 'px' : '100%' }"
                  placeholder=""
                  enter-button
                  v-model="info[item.key]"
                  clearable
                >
                  <Icon type="ios-search" slot="suffix" />
                </Input>
                <treeselect
                  v-if="item.type == 'vue-treeselect'"
                  placeholder=" "
                  :limit="item.maxTagCount || 2"
                  :limitText="maxTagPlaceholder"
                  :multiple="item.multiple"
                  :options="item.option"
                  v-model="info[item.key]"
                  :normalizer="item.normalizer"
                  :flat="(item && item.flat) || false"
                  :value-consists-of="item.valueConsistsOf"
                  noChildrenText="没有组织选择"
                  noOptionsText="暂无数据"
                  :style="{ width: item.width ? item.width + 'px' : '100%' }"
                />
              </FormItem>

              <!-- 普通即时搜索 -->
              <!-- <el-autocomplete
              v-if="item.type == 'instanceInput'"
              v-model="infoSearch[item.key]"
              :fetch-suggestions="(val, cb) => instantSearch(val, cb, item)"
              placeholder="请输入内容"
              @select="(val) => selectAutoComplete(val, item)"
              :select-when-unmatched="true"
              class="mr-6"
              :trigger-on-focus="false"
              value-key="userCode"
            ></el-autocomplete> -->
            </div>
            <div class="searchBar">
              <div class="searchBtn" v-if="isSearchBtn">
                <Button class="btnsr" type="default" @click="resetFields"
                  >清空</Button
                >
                <Button
                  style="margin-left: 5px"
                  type="primary"
                  @click="changePage(1)"
                  class="btnsr"
                  >搜索</Button
                >
                <Button
                  v-if="isExport"
                  type="primary"
                  style="margin-left: 5px"
                  @click="doExport"
                  class="btnsr"
                  >导出</Button
                >
              </div>
            </div>
          </Form>
        </div>
        <!-- 按钮 -->
      </div>
      <!-- divide -->
      <!-- 筛选权限判断代码(暂时隐藏) -->
      <!-- <Divider
        v-if="isSearch && $hasOneOf(searchLimit, $store.state.user.access)"
      /> -->
      <Divider v-if="isSearch" />
      <!-- 操作(对象) -->
      <div class="flex cusbtn" v-if="Object.keys(btnAccessList).length">
        <div class="flex">
          <Button
            v-if="btnAccessList.add"
            :type="btnAccessList.add.type"
            :class="[btnAccessList.add.isShow ? 'block' : 'none', 'add-btn']"
            @click="add"
          >
            <Icon type="md-add" size="16"></Icon>
            <span>{{ btnAccessList.add.label }}</span>
          </Button>
          <Button
            v-if="btnAccessList.addChild"
            :type="btnAccessList.addChild.type"
            :class="[btnAccessList.addChild.isShow ? 'block' : 'none']"
            @click="addChild"
            >{{ btnAccessList.addChild.label }}</Button
          >
        </div>
        <div class="flex">
          <Button
            v-if="btnAccessList.batchUpdate"
            :type="btnAccessList.batchUpdate.type"
            :class="[
              btnAccessList.batchUpdate.isShow ? 'block' : 'none',
              'add-btn',
            ]"
            @click="batchUpdate"
          >
            <Icon type="md-create" size="16" />
            <span>{{ btnAccessList.batchUpdate.label }}</span>
          </Button>
          <Button
            v-if="btnAccessList.batchDelete"
            :type="btnAccessList.batchDelete.type"
            :class="[
              btnAccessList.batchDelete.isShow ? 'block' : 'none',
              'add-btn',
            ]"
            @click="batchDelete"
          >
            <Icon type="ios-trash-outline" size="16" />
            <span>{{ btnAccessList.batchDelete.label }}</span>
          </Button>
          <Button
            v-if="btnAccessList.batchChild"
            :type="btnAccessList.batchChild.type"
            :class="[btnAccessList.batchChild.isShow ? 'block' : 'none']"
            @click="addChild"
            >{{ btnAccessList.batchChild.label }}</Button
          >
        </div>
      </div>
      <!-- 操作(列表) -->
      <div class="flex cusbtn btnList" v-if="cusBtns.length">
        <div class="flex">
          <template v-for="(item, index) in cusBtns">
            <Button
              v-if="item.isShow"
              :key="index"
              :type="item.type"
              :class="['add-btn']"
              @click="openDialog(item)"
              :disabled="item.disabled"
            >
              <Icon
                v-if="item.class"
                class="iconfont"
                :class="item.class"
                style="font-size: 14px"
              ></Icon>
              <img
                v-if="item.src"
                :src="item.src"
                style="width: 14px; height: 14px"
              />
              <Icon v-if="item.custom == 'edit'" type="md-create" size="16" />
              <Icon v-if="item.custom == 'add'" type="md-add" size="16"></Icon>
              <Icon
                v-if="item.custom == 'del' || item.custom == 'batchDel'"
                type="ios-trash-outline"
                size="16"
              />
              <span>{{ item.label }}</span>
            </Button>
          </template>
        </div>
      </div>
      <!-- 表单项以及表单内容 -->
      <div
        class="t-content"
        :class="{
          isMarginTop:
            cusBtns.length ||
            (Object.values(btnAccessList) &&
              Object.values(btnAccessList).filter((it) => it).length),
        }"
      >
        <Table
          ref="tables"
          :columns="columns"
          :data="isWebPage ? webData : tabData"
          :page="page"
          :loading="loading"
          :load-data="handleLoadData"
          @on-expand="expandTable"
          :show-header="showHeader"
          :border="border"
          :stripe="stripe"
          @on-selection-change="onSelect"
          @on-row-click="rowClick"
          size="small"
        ></Table>
      </div>
    </div>
    <!-- 分页功能(后端分页) -->
    <div
      class="pagination"
      :class="{ isBorderTop: !minHeight }"
      v-if="!noRequestPage && !isWebPage"
    >
      <div class="left">
        <span>共{{ total }}条</span>
        <span class="ml-10">一页{{ info["limit.pageSize"] }}条</span>
      </div>
      <Page
        v-if="pageshow"
        :page-size="info['limit.pageSize']"
        :current="info['limit.currentPage']"
        :total="total"
        show-sizer
        @on-page-size-change="changePageSize"
        @on-change="changePage"
        transfer
      />
    </div>
    <!-- 前端分页 -->
    <webPage
      v-if="isWebPage"
      :isBorderTop="false"
      v-model="webData"
      :operationLogVoList="tabData"
      :pageSize.sync="addInfo['limit.pageSize']"
      :current.sync="addInfo['limit.currentPage']"
      :total.sync="total"
      :pageSizeOpts="[10, 20, 30, 40]"
    ></webPage>
    <!-- 验证删除弹窗 -->
    <Modal
      width="450"
      class-name="verticle"
      v-model="validateShow"
      :footer-hide="true"
    >
      <template>
        <div class="tips">
          <span>{{ delTips }}</span>
        </div>
        <Form
          :label-width="60"
          ref="validateObj"
          :model="validateObj"
          :rules="validateRules"
        >
          <FormItem label="校验" prop="validates">
            <Input
              v-model="validateObj.validates"
              placeholder="请输入‘立即删除’以校验"
            />
          </FormItem>
          <FormItem>
            <Button type="text" @click="doCancle('validateObj')">取消</Button>
            <Button type="primary" @click="doSure('validateObj')">确定</Button>
          </FormItem>
        </Form>
      </template>
      <template slot="footer"></template>
    </Modal>
    <!-- </Card> -->
  </div>
</template>

<script>
import qs from "qs";
import axios from "@/libs/api.request";
import platform from "@/config/platform";
import excel from "lay-excel";
import _ from "lodash";
// import { doExport } from "@/api/access";
// import the component
import Treeselect from "@riophae/vue-treeselect";
// import the styles
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
var timer;
export default {
  props: {
    tableList: {
      type: Array,
      default: () => [],
    },
    cusBtns: {
      type: Array,
      default: () => [],
    },
    url: {
      type: String,
      default: () => "",
    },
    urlLoad: {
      type: String,
      default: () => "",
    },
    multiple: {
      type: Boolean,
      default: () => false,
    },
    stripe: {
      type: Boolean,
      default: () => true,
    },
    rule: {
      type: Array,
      default: () => {
        return [];
      },
    },
    showHeader: {
      type: Boolean,
      default: () => true,
    },
    delKey: {
      type: Array,
      default: () => {
        return [];
      },
    },
    renderKye: {
      type: Array,
      default: () => {
        return [];
      },
    },
    visible: {
      type: Boolean,
      default: false,
    },
    border: {
      type: Boolean,
      default: false,
    },
    isSearch: {
      type: Boolean,
      default: true,
    },
    isSearchBtn: {
      type: Boolean,
      default: true,
    },
    noParent: {
      type: Boolean,
      default: false,
    },
    isExport: {
      type: Boolean,
      default: false,
    },
    // 是否自定义导出
    isCustomExport: {
      type: Boolean,
      default: false,
    },
    searchKey: {
      type: Array,
      default: () => {
        return [];
      },
    },
    columns: {
      type: Array,
      default: () => {
        return [];
      },
    },
    btns: {
      type: Array,
      default: () => {
        return [];
      },
    },
    btnAccessList: {
      type: Object,
      default: () => {
        return {
          add: "",
          update: "",
          delete: "",
          batchDelete: "",
        };
      },
    },
    addInfo: {
      type: Object,
      default: () => {},
    },
    modelHidenFn: {
      type: Function,
      default: () => {},
    },
    modelShowFn: {
      type: Function,
      default: () => {},
    },
    cMinWidth: {
      type: Number,
      default: () => {
        return 180;
      },
    },
    // 服务器类型
    platType: {
      type: String,
      default: () => {
        return "INFORMATION_PUBLISH";
      },
    },
    // 批量删除参数名
    batchAttr: {
      type: String,
      default: () => {
        return "ids";
      },
    },
    // 批量删除额外参数名
    otherBatchAttr: {
      type: Object,
      default: () => {
        return {};
      },
    },
    // 批量删除地址
    delUrl: {
      type: String,
      default: () => {
        return "delete";
      },
    },
    // 批量删除方法
    batchMethod: {
      type: String,
      default: () => {
        return "delete";
      },
    },
    // 特殊删除请求地址
    specialUrl: {
      type: String,
      default: () => {
        return "";
      },
    },
    // 只有服务名称，没有方法名的删除地址
    onlyDelUrl: {
      type: String,
      default: () => {
        return "";
      },
    },
    // 删除子用户角色详情
    delChildRole: {
      type: String,
      default: () => {
        return "";
      },
    },
    // 删除子用户角色详情
    delRole: {
      type: String,
      default: () => {
        return "";
      },
    },
    // 是否需要输入验证删除
    isValidateDel: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    // 清空表单是否重置请求
    resetRequest: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
    // 搜索权限
    searchLimit: {
      type: Array,
      default: () => {
        return [];
      },
    },
    // 删除提示
    delTips: {
      type: String,
      default: () => {
        return null;
      },
    },
    // 主用户删除
    mainUserDel: {
      type: String,
      default: () => {
        return null;
      },
    },
    // 预设角色主体详细删除
    prevDel: {
      type: String,
      default: () => {
        return null;
      },
    },
    // 页面最小高度
    minHeight: {
      type: String,
      default: () => "calc(100vh - 248px)",
    },
    // table padding
    padding: {
      type: String,
      default: () => "20px 0 10px 20px",
    },
    disName: {
      type: String,
      default: () => "",
    },
    disValue: {
      type: String,
      default: () => "",
    },
    // 打印的字段
    keys: {
      type: Object,
      default: () => {
        return {};
      },
    },
    // 类名
    className: {
      type: String,
      default: () => {
        return "";
      },
    },
    // 请求方法
    method: {
      type: String,
      default: () => {
        return "get";
      },
    },
    // 请求方法(不带分页)
    noRequestPage: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    // 分页请求时是否自动携带page
    isRequestPage: {
      type: Boolean,
      default: () => {
        return true;
      },
    },
    // 内容边框
    contentBorder: {
      type: Boolean,
      default: () => true,
    },
    // 是否在刷新列表时 将选中的数据清空
    setEmpty: {
      type: Boolean,
      default: () => true,
    },
    // 是否前端分页
    isWebPage: {
      type: Boolean,
      default: () => false,
    },
  },
  components: {
    Treeselect,
    webPage: () => import("./webPage"),
  },
  data() {
    const validateJy = (rule, value, callback) => {
      var whiteList = ["立即删除"];
      if (whiteList.indexOf(this.validateObj.validates) == -1) {
        // 对第二个密码框单独验证
        callback(new Error("请输入‘立即删除’以校验"));
      }
      callback();
    };
    return {
      pageshow: true,
      loading: false,
      visb: false,
      tData: [],
      page: {},
      uid: "0",
      total: 0,
      info: {
        "limit.currentPage": 1,
        "limit.pageSize": 10,
      },
      infoLoad: {
        "limit.currentPage": 1,
        "limit.pageSize": 10,
      },
      tabData: [],
      loadingSearch: false,
      optionList: [],
      infoSearch: {},
      validateRules: {
        validates: [
          {
            required: true,
            trigger: "blur",
            message: "请输入‘立即删除’以校验",
          },
          {
            validator: validateJy,
            trigger: "blur",
          },
        ],
      },
      validateObj: {
        validates: "",
      },
      validateShow: false,
      delId: "",
      delIds: [],
      arr: [],
      selectVal: [],
      webData: [], // 前端分页数据
    };
  },
  watch: {
    visible: {
      handler(nval) {
        if (nval) {
          this.deleteColumns();
        } else {
          this.initColumns();
        }
      },
      immediate: true,
    },
    searchKey: {
      handler(nval) {
        if (nval?.length) {
          this.setDefaultSearch();
        }
      },
      deep: true,
    },
  },
  mounted() {
    // 默认设置search值
    this.setDefaultSearch();
  },
  methods: {
    // 默认设置search值
    setDefaultSearch() {
      // 默认赋值
      this.searchKey.forEach((item) => {
        // 每次进来就清空vModel中的值，防止监听到searchKey之后多次请求导致数据重复添加
        if (item.vModel) {
          this.info[item.vModel] = [];
        }
        // 如果有默认传参
        if (item?.defaultProps) {
          Object.keys(item?.defaultProps).forEach((it) => {
            if (
              item.type == "daterange" ||
              item.type == "datetimerange" ||
              item.valueType == "timerange"
            ) {
              // 时间模式下 需要单独给vModel回显
              // 因为时间绑定的字段 跟 真正的字段不一样
              this.$set(
                this.info,
                item.vModel,
                [
                  ...(this.info[item.vModel] || []),
                  item.defaultProps[it],
                ].filter((it) => it)
              );
            }
            this.info[it] = item.defaultProps[it];
          });
        }
      });
    },
    // 过滤多选信息折叠
    maxTagPlaceholder(num) {
      return "+  " + num;
    },
    // 选择级联
    changeCas(value, selectedData, item) {
      var len = value.length - 1;
      this.info[item.key] = value[len];
    },
    async changeTimePicker(val, func, item) {
      // 范围
      if (item.valueType == "timerange") {
        var res = await func();
        // 设置年月日
        this.info[res["start"]] = val[0];
        this.info[res["end"]] = val[1];
      }
    },
    // 过滤搜索框label
    formatterLabel(item, index) {
      // var tip = ["请选择", "请输入"];
      // var one = item.placeholder.substring(0, 3);
      // if (tip.includes(one)) {
      var tip = /(请输入|请选择)/gi;
      if (item.label) {
        return item.label;
      } else {
        return item.placeholder.replace(tip, "");
      }
      // }
    },
    // 表头操作
    openDialog(item) {
      if (item.custom == "del") {
        this.dels();
      } else if (item.custom == "delsBatch") {
        this.delsBatch();
      } else if (item.custom == "batchDel") {
        this.batchDelete();
      } else {
        if (item.custom == "detail" || item.custom == "edit") {
          var panduan = this.panduan();
          if (panduan) {
            this.$emit(
              "openDialog",
              item,
              this.selectVal[0],
              item.custom == "detail" // 是否禁用操作
            );
          }
        } else if (item.custom == "custom") {
          // 单独自定义操作
          var panduan = this.panduan();
          // this.$emit("openDialog", item, this.selectVal);
          if (panduan) this.$emit("openDialog", item, this.selectVal[0]);
        } else if (item.custom == "mulCustom") {
          // 批量自定义操作 判断是否选择了数据
          var mulPanduan = this.mulPanduan();
          if (mulPanduan) {
            this.$emit(
              "openDialog",
              item,
              this.selectVal[0],
              false,
              this.selectVal
            );
          }
        } else {
          this.$emit("openDialog", item);
        }
      }
      this.$btnBlur();
    },

    // 多选判断
    mulPanduan() {
      if (!this.selectVal.length) {
        this.$Message.warning("请至少选择一条数据");
        return false;
      }
      return true;
    },
    // 单选判断
    panduan() {
      if (!this.selectVal.length) {
        this.$Message.warning("请至少选择一条数据");
        return false;
      }
      if (this.selectVal.length > 1) {
        this.$Message.warning("请选择一条数据");
        return false;
      }
      return true;
    },
    // 表头单独删除（默认删除）
    dels() {
      if (!this.selectVal.length) {
        return this.$Message.warning("请至少选择一条数据");
      }
      if (this.selectVal.length > 1) {
        return this.$Message.warning(
          "请选择一条数据，如果要删除多条数据，请使用批量删除"
        );
      }
      this.$Modal.confirm({
        title: "提示",
        content: "确认删除吗？",
        onOk: () => {
          this.del(this.selectVal[0].id, this.selectVal[0])
            .then((d) => {
              this.init();
              this.$Message.success("删除成功");
            })
            .catch((e) => {
              let ev = e.msg ? e.msg : e.message;
              this.$Message.error(ev);
            });
        },
      });
    },
    // 表头单独删除（使用批量删除接口）
    delsBatch() {
      if (!this.selectVal.length) {
        return this.$Message.warning("请至少选择一条数据");
      }
      if (this.selectVal.length > 1) {
        return this.$Message.warning(
          "请选择一条数据，如果要删除多条数据，请使用批量删除"
        );
      }
      this.$Modal.confirm({
        title: "提示",
        content: "确认删除选中的数据吗？",
        onOk: () => {
          var obj = {};
          obj[this.batchAttr] = this.delIds;
          return axios
            .request({
              url: this.$platform[this.platType] + `${this.url}/${this.delUrl}`,
              method: this.batchMethod,
              data: {
                ...obj,
                ...this.otherBatchAttr,
              },
            })
            .then((res) => {
              this.init();
              this.$Message.success("删除成功");
            })
            .catch((err) => {
              this.$Message.error(err?.msg);
            });
        },
      });
    },
    deleteColumns() {
      var index = this.columns.findIndex((el) => el.label == "操作");
      if (index > -1) {
        this.columns.splice(index, 1);
      }
    },
    // 初始化操作
    initColumns() {
      if (this.visible) {
      } else {
        this.columns.push({
          title: "操作",
          key: "userCode",
          width: this.cMinWidth,
          align: "center",
          render: (h, params) => [
            ...this.btns.map((item) => {
              if (item.status != undefined) {
                return h(
                  "Button",
                  {
                    style: {
                      marginRight: "5px",
                      display:
                        item.isShow && item.status == params.row.status
                          ? "inline-block"
                          : "none", // 按钮权限
                      color: "#0084ff",
                      cursor: "pointer",
                    },
                    props: {
                      type: item.config.type || "primary",
                      size: "small",
                    },
                    on: {
                      click: () => {
                        item.config.click(params);
                      },
                    },
                  },
                  item.title
                );
              } else if (item.roleType) {
                return h(
                  "Button",
                  {
                    props: {
                      type: item.config.type || "primary",
                      size: "small",
                    },
                    attrs: {
                      disabled: params.row.role.roleType != 2,
                    },
                    style: {
                      marginRight: "5px",
                      display: item.isShow ? "inline-block" : "none", // 按钮权限
                      cursor: "pointer",
                      color: "#0084ff",
                    },
                    on: {
                      click: () => {
                        item.config.click(params);
                      },
                    },
                  },
                  item.title
                );
              } else {
                return h(
                  "Button",
                  {
                    style: {
                      marginRight: "5px",
                      display: item.isShow ? "inline-block" : "none", // 按钮权限
                      color: "#0084ff",
                      cursor: "pointer",
                    },
                    props: {
                      type: item.config.type || "primary",
                      size: "small",
                    },
                    on: {
                      click: () => {
                        item.config.click(params);
                      },
                    },
                  },
                  item.title
                );
              }
            }),
            h(
              "Button",
              {
                props: {
                  type: "text",
                  size: "small",
                  disabled: params.row[this.disName] == this.disValue,
                },
                style: {
                  marginRight: "5px",
                  display: this.btnAccessList?.update?.isShow
                    ? "inline-block"
                    : "none", // 按钮权限
                  cursor: "pointer",
                },
                on: {
                  click: async () => {
                    await this.$emit("edit", params);
                  },
                },
              },
              "编辑"
            ),
            h(
              "Button",
              {
                props: {
                  type: "text",
                  size: "small",
                  disabled: params.row[this.disName] == this.disValue,
                },
                style: {
                  marginRight: "5px",
                  display: this.btnAccessList?.delete?.isShow
                    ? "inline-block"
                    : "none",
                  cursor: "pointer",
                },
                on: {
                  click: () => {
                    if (this.specialUrl != "") {
                      this.$Modal.confirm({
                        title: "提示",
                        content: "确认删除吗？",
                        onOk: () => {
                          this.delSpecial(params.row.mainUserId, {
                            appId: params.row.appId,
                          })
                            .then((d) => {
                              this.init();
                              this.$Message.success("删除成功");
                            })
                            .catch((e) => {
                              let ev = e.msg ? e.msg : e.message;
                              this.$Message.error(ev);
                            });
                        },
                        onCancel: () => {},
                      });
                    } else if (this.delChildRole != "") {
                      this.$Modal.confirm({
                        title: "提示",
                        content: "确认删除吗？",
                        onOk: () => {
                          this.delChildRoleDetail(params.row.subUserId, {
                            roleId: params.row.roleId,
                          })
                            .then((d) => {
                              this.init();
                              this.$Message.success("删除成功");
                            })
                            .catch((e) => {
                              let ev = e.msg ? e.msg : e.message;
                              this.$Message.error(ev);
                            });
                        },
                        onCancel: () => {},
                      });
                    } else if (this.delRole != "") {
                      this.$Modal.confirm({
                        title: "提示",
                        content: "确认删除吗？",
                        onOk: () => {
                          this.delRoleDetail(params.row.mainUserId, {
                            roleId: params.row.roleId,
                          })
                            .then((d) => {
                              this.init();
                              this.$Message.success("删除成功");
                            })
                            .catch((e) => {
                              let ev = e.msg ? e.msg : e.message;
                              this.$Message.error(ev);
                            });
                        },
                        onCancel: () => {},
                      });
                    } else {
                      if (this.isValidateDel == true) {
                        this.validateShow = true;
                        this.delId = params.row.id;
                      } else {
                        this.$Modal.confirm({
                          title: "提示",
                          content: "确认删除吗？",
                          onOk: () => {
                            this.del(params.row.id, params.row)
                              .then((d) => {
                                this.init();
                                this.$Message.success("删除成功");
                                if (this.$parent.$refs.tree) {
                                  this.$parent.$refs.tree.getTreeList();
                                }
                              })
                              .catch((e) => {
                                let ev = e.msg ? e.msg : e.message;
                                this.$Message.error(ev);
                              });
                          },
                        });
                      }
                    }
                  },
                },
              },
              this.btnAccessList?.delete?.label
            ),
          ],
        });
      }
    },

    // 导出
    doExport() {
      var info = {};
      var filter = this.searchKey.filter((el) => el.vModel);
      Object.keys(this.info).forEach((el) => {
        var boolean = filter.some((ele) => ele.vModel == el);
        if (!boolean) {
          info[el] = this.info[el];
        }
      });
      // 排序
      var isSort = { sort: "dataCreateTime", order: "desc" };
      // 自定义导出
      if (this.isCustomExport) {
        // 不带分页
        if (this.noRequestPage) {
          delete info["limit.currentPage"];
          delete info["limit.pageSize"];
        }
        return this.$emit("doExport", { ...info, ...isSort, ...this.addInfo });
      }

      this.$Modal.confirm({
        title: "确认导出数据？",
        content: "默认导出所有，筛选请输入搜索条件",
        onOk: () => {
          doExport({ ...info, ...this.addInfo })
            .then((res) => {
              this.$downLoadExcel(res, "通行单");
            })
            .catch((err) => {
              this.$Message.error(err?.msg);
            });
        },
        onCancel: () => {},
      });
    },
    // 导出
    exportExcel(val, keys, obj) {
      // 要显示的数据
      var data = excel.filterExportData(val, keys);
      // 表头
      data.unshift(obj);
      // 3. 执行导出函数，系统会弹出弹框
      excel.exportExcel(
        {
          sheet1: data,
        },
        "数据.xlsx",
        "xlsx"
      );
    },
    doCancle(name) {
      this.validateShow = false;
      this.$refs[name].resetFields();
    },
    doSure(name) {
      this.$refs[name].validate((valid) => {
        if (valid) {
          this.del(this.delId)
            .then((d) => {
              this.init();
              this.$Message.success("删除成功");
              this.validateShow = false;
              this.$refs[name].resetFields();
            })
            .catch((e) => {
              let ev = e.msg ? e.msg : e.message;
              this.$Message.error(ev);
            });
        } else {
        }
      });
    },
    selectAutoComplete(val, item) {
      this.info[item.key] = val.id;
      delete this.info[item.instantKey];
    },
    instantSearch(val, cb, item) {
      clearTimeout(timer);
      if (val != "") {
        this.loadingSearch = true;
        if (item.findurl != "") {
          var obj = {};
          obj[item.instantKey] = val;
          if (this.platType != "") {
            timer = setTimeout(() => {
              axios
                .request({
                  url: platform[this.platType] + `${item.findurl}`,
                  method: "get",
                  params: {
                    ...obj,
                  },
                })
                .then((res) => {
                  // 即时搜索(搜索框内容变化就变为手动输入)
                  delete this.info[item.key];
                  this.info[item.instantKey] = val;
                  // this.optionList = res.data.data.userList;
                  cb(res.data.data.userList);
                  this.loadingSearch = false;
                });
            }, 300);
          } else {
            timer = setTimeout(() => {
              axios.request({
                url: platform.AUTH + `${item.findurl}`,
                method: "get",
                params: {
                  ...obj,
                },
              });
            }, 300);
          }
        }
      } else {
        cb([]);
      }
    },
    // 选择日期
    async changeDate(val, type, func, item) {
      var res = await func();
      // 如果需要时分秒
      if (item.needSec && val.filter((it) => it)?.length) {
        val[0] = val[0] + " 00:00:00";
        val[1] = val[1] + " 23:59:59";
      }
      this.info[res["start"]] = val[0];
      this.info[res["end"]] = val[1];
      this.info[item.vModel] = [val[0], val[1]].filter((it) => it);
    },
    // 选择日期（带时分秒）
    async changeTimeDate(val, type, func, item) {
      var res = await func();
      // 不需要默认时分秒
      if (!item.needSec) {
        // 设置年月日
        this.info[res["start"]] = val[0];
        this.info[res["end"]] = val[1];
      } else {
        // 默认情况下 不选择时间
        // 自己传入format时候的判断
        if (item.format) {
          // 如果是时分
          if (item.format.slice(-5) === "HH:mm") {
            if (val.filter((it) => it)?.length) {
              // 默认不选择时间的时候
              if (type == "date" && val[1].slice(-5) === "00:00") {
                if (item.isDefaultMiao) {
                  val[0] = val[0] + ":00";
                  val[1] = val[1].slice(0, -5) + "23:59:59";
                } else {
                  val[1] = val[1].slice(0, -5) + "23:59";
                }
              }
              // 选择时间的时候
              if (type == "time") {
                if (item.isDefaultMiao) {
                  val[0] = val[0] + ":00";
                  val[1] = val[1] + ":59";
                }
              }
            }
          }
        } else {
          if (
            val.filter((it) => it)?.length &&
            type == "date" &&
            val[1].slice(-8) === "00:00:00"
          ) {
            val[1] = val[1].slice(0, -8) + "23:59:59";
          }
        }

        this.info[res["start"]] = val[0];
        this.info[res["end"]] = val[1];
      }
      // this.info[item.vModel] = [val[0], val[1]].filter((it) => it);
      var times = [val[0], val[1]].filter((it) => it);
      this.$set(this.info, item.vModel, times);
      this.$forceUpdate();
    },
    async expandTable(row, status) {
      await this.$emit("expandTable", { row, status });
    },
    async handleLoadData(item, callback) {
      await this.getLoad({ ...this.infoLoad, mainUserId: item.id })
        .then((d) => {
          // this.tabData = d.data.list;
          callback(d.data.list);
        })
        .catch((err) => {});
    },
    // 重置搜索条件
    resetFields() {
      this.info = this.$options.data().info;
      this.infoSearch = {};
      if (this.resetRequest) {
        this.$nextTick(function () {
          this.init();
        });
      }
    },
    // 添加
    async add() {
      await this.$emit("add");
    },
    // 选中
    onSelect(val) {
      this.delIds = val.map((el) => el.id);
      this.selectVal = val;
      this.$emit("setSelects", val);
    },
    // 点击行
    rowClick(val, index) {
      if (!this.$findTarget(event.target)) {
        var objData = this.$refs.tables.objData;
        if (objData[index]._isChecked) {
          objData[index]._isChecked = false;
        } else {
          objData[index]._isChecked = true;
        }
        var arr = [];
        for (var item in objData) {
          if (objData[item]._isChecked) arr.push(objData[item]);
        }
        this.delIds = arr.map((el) => el.id);
        this.selectVal = arr;

        this.$emit("setSelects", this.selectVal);
        // this.$refs.tables.toggleSelect(index); // 重点 选中勾选
      }
    },
    // 批量‘编辑’
    async batchUpdate() {
      if (!this.selectVal.length) {
        this.$Message.warning("请选择一条数据");
      } else if (this.selectVal.length > 1) {
        this.$Message.warning("请选择一条数据");
      } else {
        this.$emit("batchUpdate", this.selectVal);
      }
    },
    // 批量删除
    async batchDelete() {
      if (!this.selectVal.length) {
        return this.$Message.warning("请至少选择一条数据");
      }
      this.$Modal.confirm({
        title: "提示",
        content: "确认删除选中的数据吗？",
        onOk: () => {
          var obj = {};
          obj[this.batchAttr] = this.delIds;
          var url = this.onlyDelUrl ? this.onlyDelUrl : this.url;
          return axios
            .request({
              url: this.$platform[this.platType] + `${url}/${this.delUrl}`,
              method: this.batchMethod,
              data: {
                ...obj,
                ...this.otherBatchAttr,
              },
            })
            .then((res) => {
              this.init();
              this.$Message.success("删除成功");
              // 抛出方法
              this.$emit("closeDias");
            })
            .catch((err) => {
              this.$Message.error(err?.msg);
            });
        },
      });
    },
    // 子添加
    addChild() {
      this.$emit("addChild");
    },
    async init() {
      // 清空选中的数据
      this.selectVal = [];
      var info = {};
      var filter = this.searchKey.filter((el) => el.vModel);
      Object.keys(this.info).forEach((el) => {
        var boolean = filter.some((ele) => ele.vModel == el);
        if (!boolean) {
          info[el] = this.info[el];
        }
      });
      this.loading = true;
      // this.info.roleType =+''
      await this.get({ ...this.addInfo, ...info })
        .then((d) => {
          this.loading = false;
          // 删除某一页的数据之后，这一页数据变为空时，当前页数需要-1，回到上一页
          if (d.data?.list) {
            if (d.data.list.length == 0 && this.info["limit.currentPage"] > 1) {
              this.info["limit.currentPage"] =
                this.info["limit.currentPage"] - 1;
              this.init();
            } else {
              if (this.setEmpty) {
                this.$emit("setSelects", []);
              }
              d.data.list.forEach((el, index) => {
                el.activeIndex = parseInt(index) + 1;
              });
              d.data.list.forEach((el) => {
                el._loading = false;
                el.children = [];
              });
              this.tabData = d.data.list;
              this.total = parseInt(d.data.pagination.total);
            }
          } else {
            this.tabData = d.data;
            this.total = parseInt(this.tabData.length);
          }
        })
        .catch((err) => {
          this.loading = false;
        });
    },
    get(params) {
      var obj = {
        method: this.method,
      };
      if (this.noRequestPage) {
        // 删除分页
        delete params["limit.currentPage"];
        delete params["limit.pageSize"];
      }
      var isPage = this.isRequestPage ? "/page" : "";
      obj["url"] = platform[this.platType] + `${this.url}` + isPage;
      if (this.method == "post") {
        obj["data"] = { sort: "dataCreateTime", order: "desc", ...params };
      } else {
        obj["params"] = { sort: "dataCreateTime", order: "desc", ...params };
      }
      return axios.request({
        ...obj,
      });
    },
    changePage(num) {
      if (this.noParent) {
        delete this.info?.parentId;
      }
      if (num == 1) {
        this.pageshow = false;
        this.info["limit.currentPage"] = 1;
        this.init();
        ("limit.currentPage=1");
        this.$nextTick(() => {
          this.pageshow = true;
        });
        this.info["limit.currentPage"] = num;
        return;
      }
      this.info["limit.currentPage"] = num;
      this.init();
    },
    dochangePage(num) {
      if (num == 1) {
        this.pageshow = false;
        this.info["limit.currentPage"] = 1;
        this.init();
        ("limit.currentPage=1");
        this.$nextTick(() => {
          this.pageshow = true;
        });
        this.info["limit.currentPage"] = num;
        return;
      }
      this.info["limit.currentPage"] = num;
      this.init();
    },
    changePageSize(size) {
      this.info["limit.pageSize"] = size;
      this.init();
    },
    // add(data) {
    //   return axios.request({
    //     url: this.url,
    //     method: "post",
    //     data: {
    //       ...this.addInfo,
    //       ...data,
    //     },
    //   });
    // },
    del(id, row) {
      if (this.mainUserDel == "mainUserDel") {
        return axios.request({
          url: platform[this.platType] + `${this.url}/logic/` + id,
          method: "delete",
          params: {
            deleteValid: "立即删除",
          },
        });
      } else if (this.prevDel == "prevDel") {
        return axios.request({
          url: platform[this.platType] + `${this.url}/` + row.roleId,
          method: "delete",
          params: {
            mainUserId: row.mainUserId,
          },
        });
      } else {
        return axios.request({
          url: platform[this.platType] + `${this.url}/` + id,
          method: "delete",
        });
      }
    },
    delSpecial(id, params) {
      return axios.request({
        url: platform[this.platType] + `${this.specialUrl}/${id}`,
        method: "delete",
        params,
      });
    },
    delChildRoleDetail(id, params) {
      return axios.request({
        url: platform[this.platType] + `${this.delChildRole}/${id}`,
        method: "delete",
        params,
      });
    },
    delRoleDetail(id, params) {
      return axios.request({
        url: platform[this.platType] + `${this.delRole}/${id}`,
        method: "delete",
        params,
      });
    },
    edit(data) {
      return axios.request({
        url: this.url,
        method: "put",
        data,
      });
    },
    getLoad(params) {
      return axios.request({
        url: platform[this.platType] + `${this.urlLoad}/page`,
        method: "get",
        params: { ...params, sort: "dataCreateTime", order: "desc" },
      });
    },
    getDetails(id, params) {
      return axios
        .request({
          url: platform[this.platType] + `${this.url}/app-page?companyId=` + id,
          method: "get",
          params,
        })
        .then((res) => {
          (this.tData = res.data.list), (this.page = res.data.pagination);
        });
    },
  },
};
</script>
<style lang="scss" scoped>
@import "@/style/table.scss";
.searchInput ::v-deep {
  .ivu-form-item {
    margin-bottom: 10px;
  }
  .ivu-select-multiple {
    .ivu-select-input {
    }
  }
}
.tables.left ::v-deep {
  .ivu-table-row {
    .ivu-table-column-center:nth-child(3) {
      text-align: left !important;
      p {
        max-width: 197px;
        overflow: hidden;
        white-space: nowrap;
        text-overflow: ellipsis;
      }
    }
  }
}
.tables ::v-deep {
  height: 100%;
  .ivu-date-picker {
    width: 290px;
  }
  .vue-treeselect {
    .vue-treeselect__control {
      margin-top: 1.77px;
      height: 32px !important;
      .vue-treeselect__value-container {
        line-height: 2 !important;
      }
      .vue-treeselect__limit-tip {
        padding-right: 0 !important;
        padding-top: 0 !important;
      }
    }
  }
  .add-btn {
    & > span {
      display: flex;
      align-items: center;
      gap: 0 3px;
      .iconfont {
        margin-top: 1px;
      }
    }
  }
  // divide线条
  .ivu-divider {
    width: calc(100% + 20px);
    margin: 0px 0 14px -20px !important;
  }
  .t-content {
    &.isMarginTop {
      margin-top: 14px;
    }
  }
  // flex下button
  .cusbtn {
    .flex {
      .ivu-btn {
        padding: 0 15px 0;
      }
    }
  }
  .tableContent {
    min-height: var(--minHeight);
    padding: var(--padding);
    background-color: #fff;
    box-sizing: content-box;
    &.border {
      border-left: 1px solid #e9e7ea;
      border-right: 1px solid #e9e7ea;
    }
    .searchInput {
      width: 100%;
      .ivu-form {
        width: 100%;
        display: flex;
        flex-wrap: wrap;
        gap: 0 20px;
      }
    }
  }
  .ivu-table-wrapper {
    border-left: 1px solid #e9e7ea !important;
    border-top: 1px solid #e9e7ea !important;
  }
  .ivu-table th,
  .ivu-table td {
    border-right: 1px solid #e9e7ea;
    border-bottom: 1px solid #e9e7ea;
  }
  .ivu-table-header {
    .ivu-table-column-center {
      height: 40px;
      background-color: #ebeff8 !important;
      color: #232b31;
    }
  }

  .searchBar {
    display: flex;
    flex-shrink: 0;
    // padding-right: 40px;
    flex-direction: row-reverse;
    padding-right: 2%;
    padding-top: 14px;
    margin-left: auto;
    align-items: center;
  }
  .el-autocomplete {
    height: 32px;
    .el-input {
      height: 100%;
      input {
        height: 100%;
      }
    }
  }
  // tips提示
  .searchs {
    position: relative;
    padding-right: 40px;
    .tips {
      position: absolute;
      min-width: 300px;
      top: -16px;
    }
  }
}
.block {
  display: inline-block;
}
.none {
  display: none;
}
</style>
<style lang="scss">
.verticle {
  .ivu-form-item:last-child {
    margin-bottom: 0;
    text-align: right;
  }
  .tips {
    margin-bottom: 10px;
    padding-left: 40px;
    margin-top: 10px;
    img {
      width: 30px;
      height: 30px;
    }
    span {
      margin-left: 15px;
      max-width: 300px;
      display: inline-block;
    }
  }
}
</style>
